﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Pakxel.Data;
using Telerik.WinControls.UI;
using System.Data.Common;
using System.Collections.ObjectModel;

namespace Pakxel.SmartLogistic
{
    public partial class LiquidacionWorkBench : RadForm
    {
        private delegate bool RuleManager(string CString);
        private Pakxel.Framework.Rules ruleToCheck;
        private RuleManager IsNumeric;
        private MEDataDataContext DataContext;
        T016 Liq;

        public LiquidacionWorkBench()
        {
            InitializeComponent();
        }

        private void LiquidacionWorkBench_Load(object sender, EventArgs e)
        {
            WorkBenchFilter.TextBox.BackColor = Color.LightYellow;
            DataContext = new Data.MEDataDataContext(WorkBench.ConnectionString);            
            WorkBenchFilter.KeyDown += WorkBenchFilter_KeyDown;
            Descuentos.Rows.CollectionChanged += Rows_CollectionChanged;
            Comprobantes.Rows.CollectionChanged += Rows_CollectionChanged;
            ViajesGrid.Rows.CollectionChanged += VRows_CollectionChanged;
            ruleToCheck = new Framework.Rules();
            IsNumeric = new RuleManager(ruleToCheck.IsNumeric);
            FilterSelector.SelectedIndex = 0;
        }

        void UpdateCompDesc()
        { 
            if (DataContext.Connection.State == ConnectionState.Closed)
                    DataContext.Connection.Open();

            using (DbTransaction transaction = DataContext.Connection.BeginTransaction(IsolationLevel.Serializable))
            {
                DataContext.Transaction = transaction;
                try
                {
                    DataContext.SubmitChanges();
                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    MainApp.WriteExceptionToLog(ex);
                }
                finally
                {
                    DataContext.Connection.Close();
                }
            }
        }

        void VRows_CollectionChanged(object sender, Telerik.WinControls.Data.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case Telerik.WinControls.Data.NotifyCollectionChangedAction.Add:
                case Telerik.WinControls.Data.NotifyCollectionChangedAction.Remove:
                    if (ViajesGrid.RowCount > 0)
                        Kms.Value = (from V in DataContext.T005s
                                     where
                                         (from I in ViajesGrid.Rows select I.Cells["viaje"].Value).ToArray().Contains(V.T005NoViaje)
                                     select V.T005Kilometros).Sum();
                        
                    else
                        Kms.Value = 0;

                    UpdateTotalsCD(Descuentos);
                    UpdateTotalsCD(Comprobantes);
                    break;

                default:
                    break;
            }
        }

        void Rows_CollectionChanged(object sender, Telerik.WinControls.Data.NotifyCollectionChangedEventArgs e)
        {
            char tipo = (Descuentos.Focused ? 'D' : (Comprobantes.Focused ? 'C' : 'V'));

            if (tipo != 'V') //Que esten enfocados los comprobantes o descuentos
            {
                GridViewRowInfo gvri;
                T022 Mod;
                switch (e.Action)
                {
                    case Telerik.WinControls.Data.NotifyCollectionChangedAction.Add:
                        gvri = (GridViewRowInfo)e.NewItems[0];
                        T005 Viaje = (from x in DataContext.T005s where x.T005NoViaje.Equals(Convert.ToInt32(ViajesGrid.SelectedRows[0].Cells["viaje"].Value)) select x).SingleOrDefault();
                        T022 Nvo = new T022()
                        {
                            T022Monto = Convert.ToDecimal(gvri.Cells["monto"].Value),
                            T005NoViaje = Viaje.T005NoViaje,
                            T022Descripcion = (gvri.Cells["Descripcion"].Value == null ? "" : gvri.Cells["Descripcion"].Value.ToString()),
                            T022Fecha = DateTime.Now,
                            T022Tipo = tipo
                        };
                        Viaje.T022s.Add(Nvo);
                        UpdateCompDesc();
                        gvri.Cells["id"].Value = Nvo.T022IdComprobante;
                        UpdateTotalsCD(tipo == 'D' ? Descuentos : Comprobantes);

                        break;

                    case Telerik.WinControls.Data.NotifyCollectionChangedAction.ItemChanged:
                        gvri = (GridViewRowInfo)e.NewItems[0];
                        if (gvri.Cells["id"].Value != null && gvri.IsCurrent)
                        {
                            Mod = (from CD in DataContext.T022s where CD.T022IdComprobante.Equals(Convert.ToInt32(gvri.Cells["id"].Value)) select CD).SingleOrDefault<T022>();
                            Mod.T022Descripcion = gvri.Cells["Descripcion"].Value.ToString();
                            Mod.T022Monto = Convert.ToDecimal(gvri.Cells["monto"].Value);

                            UpdateCompDesc();
                            UpdateTotalsCD(tipo == 'D' ? Descuentos : Comprobantes);
                        }
                        break;

                    case Telerik.WinControls.Data.NotifyCollectionChangedAction.Remove:
                        if (Descuentos.Focused || Comprobantes.Focused)
                        {
                            gvri = (GridViewRowInfo)e.OldItems[0];
                            Mod = (from CD in DataContext.T022s where CD.T022IdComprobante.Equals(gvri.Cells["id"].Value) select CD).SingleOrDefault<T022>();
                            DataContext.T022s.DeleteOnSubmit(Mod);

                            UpdateCompDesc();
                            UpdateTotalsCD(tipo == 'D' ? Descuentos : Comprobantes);
                        }
                        break;

                    default:
                        break;
                }
            }
        }

        void UpdateTotalsCD(RadGridView sender)
        {
            List<Int32> viajes = (from V in ViajesGrid.Rows select Convert.ToInt32(V.Cells["viaje"].Value)).ToList<Int32>();

            if (sender.Name == "Descuentos")            
                try { TDescuentos.Value = (from D in DataContext.T022s where viajes.Contains(Convert.ToInt32(D.T005NoViaje)) && D.T022Tipo == 'D' select D.T022Monto).Sum();
                } catch { TDescuentos.Value = 0; }            
            else
                try { TComprobantes.Value = (from D in DataContext.T022s where viajes.Contains(Convert.ToInt32(D.T005NoViaje)) && D.T022Tipo == 'C' select D.T022Monto).Sum(); 
                } catch { TComprobantes.Value = 0; }
        }

        private void EmptyFields()
        {
            ViajesGrid.Rows.Clear();
            Comprobantes.Rows.Clear();
            Descuentos.Rows.Clear();
            foreach (Control item in radGroupBox2.Controls)
                if(item.GetType().Name == "RadTextBox")
                    ((RadTextBox)item).Text = "";

            Liquidar.Checked = false;
            Liquidar.AutoCheck = true;
            Sueldo.Value = 0;
            TComprobantes.Value = 0;
            TAnticipos.Value = 0;
            TDescuentos.Value = 0;
            Kms.Value = 0;

            Liq = null;
        }

        void Imprimir_Click(object sender, EventArgs e)
        {
            if (Liquidar.Checked && ViajesGrid.RowCount > 0)
            {
                Reportes.Liquidacion RLiq = new Reportes.Liquidacion();
                Reportes.Reportes Rpt = new Reportes.Reportes { MdiParent = MdiParent };

                //IEnumerable<T016> TLiq = (from V in DataContext.T016s where V.T016IdLiquidacion.Equals(Convert.ToInt32(NoLiquidacion.Text)) select V).ToList();
                RLiq.Database.Tables["Pakxel_Data_T016"].SetDataSource(
                    (from V in DataContext.T016s
                     where V.T016IdLiquidacion.Equals(Liq.T016IdLiquidacion)
                     select
                         new { T016IdLiquidacion = V.T016IdLiquidacion,
                         T016NoLiquidacion = V.T016NoLiquidacion,
                         T016TotalKms = V.T016TotalKms ?? 0,
                         T016Sueldo = V.T016Sueldo ?? 0,
                         T016TotalLiquidacion = V.T016TotalLiquidacion ?? 0,
                         T016Cancelada = V.T016Cancelada,
                         T016Terminada = V.T016Terminada
                         }
                    ));

                string Oper = (from V in DataContext.T005s where V.T005NoViaje.Equals(Convert.ToInt16(ViajesGrid.Rows[0].Cells["viaje"].Value)) select V.T010NoOperador).SingleOrDefault();

                Rpt.Parametros.Add("Operador", (from Op in DataContext.T010s where Op.T010NoOperador.Equals(Oper) select Op.T010Nombre).SingleOrDefault());
                Rpt.Parametros.Add("TComprobado", Convert.ToDecimal(TComprobantes.Text));
                Rpt.Parametros.Add("TDescuentos", Convert.ToDecimal(TDescuentos.Text));
                Rpt.Parametros.Add("Sueldo", Convert.ToDecimal(Sueldo.Text));
                Rpt.Parametros.Add("Kms", Convert.ToDecimal(Kms.Value));

                Int32[] Vjs = (from V in DataContext.T005s where V.T016IdLiquidacion.Equals(Liq.T016IdLiquidacion) select V.T005NoViaje).ToArray();

                //var Suma = (from T in DataContext.T012s where (Vjs.Contains(T.T005NoViaje) && T.T012Cancelado.Equals("N")) select T).Sum(T=>(double?)T.T012Monto)??0;
                                
                //var qry = DataContext.T012s.Where(od => Vjs.Contains(od.T005NoViaje));
               
                //Rpt.Parametros.Add("PGastos", (from T in DataContext.T012s where Vjs.Contains(Convert.ToInt32(T.T005NoViaje)) && T.T012Cancelado.Equals("NO") select T.T012Monto).Sum());
                Rpt.Parametros.Add("PGastos", (from T in DataContext.T012s where (Vjs.Contains(T.T005NoViaje) && T.T012Cancelado.Equals("N")) select T).Sum(T => (double?)T.T012Monto) ?? 0);
                Rpt.Parametros.Add("PDiesel", (from T in DataContext.T020s where (Vjs.Contains(T.T005NoViaje) && T.T020Cancelado.Equals("N")) select T).Sum(T=>(double?)T.T020Monto)??0);
                Rpt.Parametros.Add("TLiquidar", Convert.ToDecimal(TLiquidacion.Value));

                //IEnumerable<T022> Comp = (from C in DataContext.T022s where Vjs.Contains(C.T005NoViaje) && C.T022Tipo == 'C' select C).ToList();
                RLiq.Subreports["ComprobantesSR"].SetDataSource(
                    (from C in DataContext.T022s
                     where Vjs.Contains(C.T005NoViaje) && C.T022Tipo == 'C'
                     select
                         new { T022IdComprobante = C.T022IdComprobante,
                         T022Tipo = C.T022Tipo,
                         T005Noviaje = C.T005NoViaje,
                         T022Fecha = C.T022Fecha ?? DateTime.Now,
                         T022Descripcion = C.T022Descripcion,
                         T022Monto = C.T022Monto
                         })
                    );
                //IEnumerable<T022> Desc = (from C in DataContext.T022s where Vjs.Contains(C.T005NoViaje) && C.T022Tipo == 'D' select C).ToList();
                RLiq.Subreports["DescuentosSR"].SetDataSource(
                    (from C in DataContext.T022s
                     where Vjs.Contains(C.T005NoViaje) && C.T022Tipo == 'D'
                     select
                         new { T022IdComprobante = C.T022IdComprobante,
                             T022Tipo = C.T022Tipo,
                             T005Noviaje = C.T005NoViaje,
                             T022Fecha = C.T022Fecha ?? DateTime.Now,
                             T022Descripcion = C.T022Descripcion,
                             T022Monto = C.T022Monto
                         })
                    );
                
                IEnumerable<T011> Ctes = (from C in DataContext.T011s 
                                          where (from NC in DataContext.T005s where NC.T016IdLiquidacion.Equals(Liq.T016IdLiquidacion) 
                                                 select NC.T011Entity).ToArray().Contains(C.T011Entity) 
                                          select C).ToList();
                RLiq.Subreports["Viajes"].Database.Tables["Pakxel_Data_T011"].SetDataSource(Ctes);

                RLiq.Subreports["Viajes"].Database
                    .Tables["Pakxel_Data_ViajesView"]
                    .SetDataSource((from V in DataContext.ViajesViews
                                    where V.T016IdLiquidacion.Equals(Liq.T016IdLiquidacion)
                                    select new
                                    {
                                        T005NoViaje = V.T005NoViaje,
                                        T016IdLiquidacion = V.T016IdLiquidacion ?? 0,
                                        T005FechaInicio = V.T005FechaInicio,
                                        T005TipSer = V.T005TipSer,
                                        T005CargadoVacio = V.T005CargadoVacio,
                                        T006NoUnidad = V.T006NoUnidad,
                                        T007IdRemolque = V.T007IdRemolque,
                                        T008IdOrigen = V.T008IdOrigen,
                                        T008IdDestino = V.T008IdDestino,
                                        T009IdLinea = V.T009IdLinea,
                                        T010NoOperador = V.T010NoOperador,
                                        T005Kilometros = V.T005Kilometros,
                                        T011Entity = V.T011Entity,
                                        T005Cancelado = V.T005Cancelado,
                                        T008Origen = V.T008Origen,
                                        T008Destino = V.T008Destino
                                    }).ToList());

                Rpt.Reporte = RLiq;
                Rpt.Show();
            }
        }

        void tsbEdit_Click(object sender, EventArgs e)
        {
            //Flete100.ReadOnly = false;
        }

        void tsbNvo_Click(object sender, EventArgs e)
        {
            EmptyFields();
        }

        private void tsbGuardar_Click(object sender, EventArgs e)
        {
            if (ViajesGrid.Rows.Count > 0 && Liquidar.AutoCheck)
            {
                // Corregir cuando no tiene liquidaciones ni anticipos se agrega como nuevo, cuando ya tiene se edita ?? o se ignoran los cambios ??
                if (DataContext.Connection.State == ConnectionState.Closed)
                    DataContext.Connection.Open();

                using (DbTransaction transaction = DataContext.Connection.BeginTransaction(IsolationLevel.Serializable))
                {
                    DataContext.Transaction = transaction;
                    try
                    {
                       DataContext.Log = System.Console.Out;

                        if (Liq == null)
                        {
                            T014 Parametros = (from P in DataContext.T014s where P.T014IdParametro.Equals("FOLLIQ") select P).SingleOrDefault();
                            Parametros.T014Val1 = (Convert.ToInt32(Parametros.T014Val1) + 1).ToString();

                            NoLiquidacion.Text = Parametros.T014Val1;
                            Liq = new T016()
                            {
                                T016NoLiquidacion = Convert.ToInt32(NoLiquidacion.Text),
                                T016Sueldo = !string.IsNullOrEmpty(Sueldo.Text) ? Convert.ToDecimal(Sueldo.Text) : 0,
                                T016TotalKms = !string.IsNullOrEmpty(Kms.Text) ? Convert.ToDecimal(Kms.Text) : 0,
                                T016TotalLiquidacion = Convert.ToDecimal(TLiquidacion.Text),
                                T016Cancelada = 'N',
                                T016Terminada = Liquidar.Checked
                            };
                            DataContext.T016s.InsertOnSubmit(Liq);
                            DataContext.SubmitChanges();

                            foreach (T005 item in (from V in DataContext.T005s 
                                                   where (from I in ViajesGrid.Rows select I.Cells["viaje"].Value).ToArray().Contains(V.T005NoViaje) 
                                                   select V))
                            { item.T016IdLiquidacion = Liq.T016IdLiquidacion; }

                        }
                        else
                        {
                            Liq.T016Sueldo = !string.IsNullOrEmpty(Sueldo.Text) ? Convert.ToDecimal(Sueldo.Text) : 0;
                            Liq.T016TotalKms = !string.IsNullOrEmpty(Kms.Text) ? Convert.ToDecimal(Kms.Text) : 0;
                            Liq.T016TotalLiquidacion = Convert.ToDecimal(TLiquidacion.Text);
                            Liq.T016Terminada = Liquidar.Checked;

                            Int32[] ArrVjs = (from I in ViajesGrid.Rows select Convert.ToInt32(I.Cells["viaje"].Value)).ToArray();//viajes actuales
                            foreach (T005 item in (from V in DataContext.T005s where V.T016IdLiquidacion.Equals(Liq.T016IdLiquidacion) || ArrVjs.Contains(V.T005NoViaje) select V))//Recuperar los guardados en la DB y nuevos
                                if (ArrVjs.Contains(item.T005NoViaje))
                                    item.T016IdLiquidacion = Liq.T016IdLiquidacion;
                                else
                                    item.T016IdLiquidacion = null;
                        }

                        DataContext.SubmitChanges();
                        transaction.Commit();
                        Liquidar.AutoCheck = !Liquidar.Checked;
                        toolStripButton1.Enabled = Liquidar.Checked;
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        MainApp.WriteExceptionToLog(ex);
                    }
                    finally
                    {
                        DataContext.Connection.Close();
                    }
                }
            }
        }

        private void WorkBenchFilter_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                if (IsNumeric(WorkBenchFilter.Text))
                {
                    T016 TmpLiq = (from l in DataContext.T016s where l.T016NoLiquidacion.Equals(WorkBenchFilter.Text.Trim()) select l).SingleOrDefault();
                    if (TmpLiq != null)
                    {
                        EmptyFields();
                        Liq = TmpLiq;
                        
                        NoLiquidacion.Text = Liq.T016NoLiquidacion.ToString();
                        Kms.Value = Liq.T016TotalKms;
                        Sueldo.Value = Liq.T016Sueldo;
                        TLiquidacion.Value = Liq.T016TotalLiquidacion;
                        Liquidar.Checked = Liq.T016Terminada;
                        Liquidar.AutoCheck = !Liq.T016Terminada;
                        toolStripButton1.Enabled = Liq.T016Terminada;

                        foreach (T005 item in (from V in DataContext.T005s where V.T016IdLiquidacion.Equals(Liq.T016IdLiquidacion) select V))                        
                            ViajesGrid.Rows.Add(new object[]
                            { 
                                item.T005NoViaje, 
                                item.T011.T011Nombre,
                                string.Format("{0}-{1}", item.T008IdOrigen, item.T008IdDestino),
                                item.T005Kilometros,
                                item.T006NoUnidad
                            });
                    }
                }
        }

        private void MasterTemplate_SelectionChanged(object sender, EventArgs e)
        {
            Comprobantes.Rows.Clear();
            Descuentos.Rows.Clear();

            if (ViajesGrid.SelectedRows.Count == 1)
            {
                foreach (T022 Itm in (from C in DataContext.T022s where C.T022Tipo.Equals('C') && C.T005NoViaje.Equals(ViajesGrid.SelectedRows[0].Cells["viaje"].Value) select C))
                    Comprobantes.Rows.Add(new object[] { Convert.ToInt32(Itm.T022IdComprobante), Itm.T022Descripcion, Convert.ToDecimal(Itm.T022Monto) });
                foreach (T022 Itm in (from C in DataContext.T022s where C.T022Tipo.Equals('D') && C.T005NoViaje.Equals(ViajesGrid.SelectedRows[0].Cells["viaje"].Value) select C))
                    Descuentos.Rows.Add(new object[] { Convert.ToInt32(Itm.T022IdComprobante), Itm.T022Descripcion, Convert.ToDecimal(Itm.T022Monto) });

                foreach (RadGridView item in new RadGridView[]{ Comprobantes, Descuentos })
                {
                    item.AllowAddNewRow = true;
                    item.AllowDeleteRow = true;
                    item.AllowEditRow = true;
                }                
            } else
                foreach (RadGridView item in new RadGridView[] { Comprobantes, Descuentos })
                {
                    item.AllowAddNewRow = false;
                    item.AllowDeleteRow = false;
                    item.AllowEditRow = false;
                } 
        }

        private void Kms_TextChanged(object sender, EventArgs e)
        {
            if (ViajesGrid.RowCount > 0)
                Sueldo.Value = Convert.ToDecimal(Kms.Value) * (from O in DataContext.T005s where O.T005NoViaje.Equals(Convert.ToInt32(ViajesGrid.Rows[0].Cells["viaje"].Value)) select O.T010.T010Sueldo).Sum();
            else
                Sueldo.Value = 0;
        }

        private void TAnticipos_TextChanged(object sender, EventArgs e)
        {
            TLiquidacion.Value = 
                (Convert.ToDecimal(Sueldo.Value) + Convert.ToDecimal(TComprobantes.Value) - Convert.ToDecimal(TAnticipos.Value) - Convert.ToDecimal(TDescuentos.Value));
        }

        private void DesCom_CellValidating(object sender, CellValidatingEventArgs e)
        {
            if(e.Value == null){
                switch (e.ColumnIndex)
                {
                    case 1: e.Row.Cells[e.ColumnIndex].Value = ""; break;
                    case 2: e.Row.Cells[e.ColumnIndex].Value = 0; break;
                }
            }
        }

        private void Liquidar_CheckedChanged(object sender, EventArgs e)
        {
            Comprobantes.AllowAddNewRow = !Liquidar.Checked;
            Comprobantes.AllowEditRow = !Liquidar.Checked;

            Descuentos.AllowAddNewRow = !Liquidar.Checked;
            Descuentos.AllowEditRow = !Liquidar.Checked;

            ViajesGrid.AllowAddNewRow = !Liquidar.Checked;
            ViajesGrid.AllowDeleteRow = !Liquidar.Checked;
            ViajesGrid.AllowEditRow = !Liquidar.Checked;
        }
        
        private void ViajesGrid_UserAddingRow(object sender, GridViewRowCancelEventArgs e)
        {
           /// TODO : Validar
            T005 viaje = (from v in DataContext.T005s where v.T005NoViaje.Equals(e.Rows[0].Cells["viaje"].Value) select v).SingleOrDefault();

            if (viaje == null) { e.Cancel = true; return; } 

            bool disponible;
            if (Liq != null)
                disponible = (viaje.T016IdLiquidacion == Liq.T016IdLiquidacion) || viaje.T016IdLiquidacion == null;
            else
                disponible = viaje.T016IdLiquidacion == null;

            if (disponible && (from N in ViajesGrid.Rows where Convert.ToInt32(N.Cells["viaje"].Value).Equals(viaje.T005NoViaje) select N).Count() == 0)
            {
                e.Rows[0].Cells["cliente"].Value = viaje.T011.T011Nombre;
                e.Rows[0].Cells["ruta"].Value = string.Format("{0}-{1}", viaje.T008IdOrigen, viaje.T008IdDestino);
                e.Rows[0].Cells["kms"].Value = viaje.T005Kilometros;
                e.Rows[0].Cells["caja"].Value = viaje.T006NoUnidad;
            } else {
                MessageBox.Show("Ya esta tiene liquidacion o ya esta agregado este viaje.", "Agregar viaje");
                e.Cancel = true;
            }
        }
    }
}
